#include <stdio.h>
#include <string.h>
#include "dvc.h"
#include "dvc_log.h"
#include "mqtt/mqtt.h"

extern dvc_t gloab_dvc;

typedef enum
{
    DVC_SENSOR_TYPE_BUS_VOLTAGE, /* 总线电压 */
    DVC_SENSOR_TYPE_BUS_CURRENT, /* 总线电流 */
    DVC_SENSOR_TYPE_BUS_POWER,   /* 总线功率 */
    DVC_SENSOR_TYPE_CC_SUM_MA,   /* 库仑计-总充电容量 */
    DVC_SENSOR_TYPE_CC_SUM_mW,   /* 库仑计-总充电功率 */
    DVC_SENSOR_TYPE_CC_CHG_MA,   /* 库仑计-每日充电容量累加(每日清零) */
    DVC_SENSOR_TYPE_CC_CHG_mW,   /* 库仑计-每日充电功率累加(每日清零) */
    DVC_SENSOR_TYPE_CC_DSG_MA,   /* 库仑计-每日放电容量累加(每日清零) */
    DVC_SENSOR_TYPE_CC_DSG_mW,   /* 库仑计-每日放电功率累加(每日清零) */
    DVC_SENSOR_TYPE_SOC,         /* 剩余容量 */
    DVC_SENSOR_TYPE_SOH,         /* 电池健康度 */
    DVC_SENSOR_TYPE_ALERT,       /* 警报状态 */
    DVC_SENSOR_TYPE_SOC_TIME,    /* 剩余运行时间 */
    DVC_SENSOR_TYPE_BAT_DIFF,    /* 电池压差 */
    DVC_SENSOR_TYPE_BAT1,        /* 电池1电压 */
    DVC_SENSOR_TYPE_BAT2,        /* 电池2电压 */
    DVC_SENSOR_TYPE_BAT3,        /* 电池3电压 */
    DVC_SENSOR_TYPE_BAT4,        /* 电池4电压 */
    DVC_SENSOR_TYPE_BAT5,        /* 电池5电压 */
    DVC_SENSOR_TYPE_BAT6,        /* 电池6电压 */
    DVC_SENSOR_TYPE_AFE_TEMP,    /* AFE温度 */
    DVC_SENSOR_TYPE_BAT_TEMP,    /* 电池温度 */
    DVC_SENSOR_TYPE_MAX,
} dvc_sensor_type_t;

static uint8_t get_dvc_sensor_state(void *user_data, uint8_t id, char *buf, uint8_t len)
{
    if (!gloab_dvc || id >= DVC_SENSOR_TYPE_MAX)
        return 0;
    dvc_t dvc = gloab_dvc;
    if (id == DVC_SENSOR_TYPE_BUS_VOLTAGE)
        return snprintf(buf, len, "%f", dvc->voltage);
    else if (id == DVC_SENSOR_TYPE_BUS_CURRENT)
        return snprintf(buf, len, "%f", dvc->current);
    else if (id == DVC_SENSOR_TYPE_BUS_POWER)
        return snprintf(buf, len, "%f", dvc->power);

    else if (id == DVC_SENSOR_TYPE_CC_SUM_MA)
        return snprintf(buf, len, "%f", dvc->coulomb_counter.sum.mA / 3600.0f);
    else if (id == DVC_SENSOR_TYPE_CC_SUM_mW)
        return snprintf(buf, len, "%f", dvc->coulomb_counter.sum.mW / 3600.0f);
    else if (id == DVC_SENSOR_TYPE_CC_CHG_MA)
        return snprintf(buf, len, "%f", dvc->coulomb_counter.chg.mA / 3600.0f);
    else if (id == DVC_SENSOR_TYPE_CC_CHG_mW)
        return snprintf(buf, len, "%f", dvc->coulomb_counter.chg.mW / 3600.0f);
    else if (id == DVC_SENSOR_TYPE_CC_DSG_MA)
        return snprintf(buf, len, "%f", dvc->coulomb_counter.dsg.mA / 3600.0f);
    else if (id == DVC_SENSOR_TYPE_CC_DSG_mW)
        return snprintf(buf, len, "%f", dvc->coulomb_counter.dsg.mW / 3600.0f);

    else if (id == DVC_SENSOR_TYPE_SOC)
        return snprintf(buf, len, "%f", dvc->coulomb_counter.bat_rmA * 100 / dvc->coulomb_counter.bat_mA);
    else if (id == DVC_SENSOR_TYPE_SOH)
        return snprintf(buf, len, "%.3f", dvc->coulomb_counter.bat_health * 100);
    else if (id == DVC_SENSOR_TYPE_ALERT)
        return snprintf(buf, len, "%u", dvc->alert);
    else if (id == DVC_SENSOR_TYPE_SOC_TIME)
        return snprintf(buf, len, "%lu", dvc->coulomb_counter.bat_rtime / 1000 / 60);

    else if (id == DVC_SENSOR_TYPE_BAT_DIFF)
        return snprintf(buf, len, "%u", dvc->bat_diff);
    else if (id == DVC_SENSOR_TYPE_BAT1)
        return snprintf(buf, len, "%d.%03d", dvc->bat_vol[0] / 1000, dvc->bat_vol[0] % 1000);
    else if (id == DVC_SENSOR_TYPE_BAT2)
        return snprintf(buf, len, "%d.%03d", dvc->bat_vol[1] / 1000, dvc->bat_vol[1] % 1000);
    else if (id == DVC_SENSOR_TYPE_BAT3)
        return snprintf(buf, len, "%d.%03d", dvc->bat_vol[2] / 1000, dvc->bat_vol[2] % 1000);
    else if (id == DVC_SENSOR_TYPE_BAT4)
        return snprintf(buf, len, "%d.%03d", dvc->bat_vol[3] / 1000, dvc->bat_vol[3] % 1000);
    else if (id == DVC_SENSOR_TYPE_BAT5)
        return snprintf(buf, len, "%d.%03d", dvc->bat_vol[4] / 1000, dvc->bat_vol[4] % 1000);
    else if (id == DVC_SENSOR_TYPE_BAT6)
        return snprintf(buf, len, "%d.%03d", dvc->bat_vol[5] / 1000, dvc->bat_vol[5] % 1000);

    else if (id == DVC_SENSOR_TYPE_AFE_TEMP)
        return snprintf(buf, len, "%f", dvc->mcu_temp);
    else if (id == DVC_SENSOR_TYPE_BAT_TEMP)
        return snprintf(buf, len, "%f", dvc->temp);
    return 0;
}

ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BUS_VOLTAGE, bus_voltage, "V", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BUS_CURRENT, bus_current, "A", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BUS_POWER, bus_power, "W", get_dvc_sensor_state, NULL);

ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_CC_SUM_MA, sum_mah, "Ah", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_CC_SUM_mW, sum_mwh, "Wh", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_CC_CHG_MA, chg_mah, "Ah", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_CC_CHG_mW, chg_mwh, "Wh", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_CC_DSG_MA, dsg_mah, "Ah", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_CC_DSG_mW, dsg_mwh, "Wh", get_dvc_sensor_state, NULL);

ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_SOC, soc, "%", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_SOH, soh, "%", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_ALERT, afe_alert, NULL, get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_SOC_TIME, soc_time, "min", get_dvc_sensor_state, NULL);

ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BAT_DIFF, bat_diff, "mV", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BAT1, bat1_voltage, "V", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BAT2, bat2_voltage, "V", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BAT3, bat3_voltage, "V", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BAT4, bat4_voltage, "V", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BAT5, bat5_voltage, "V", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BAT6, bat6_voltage, "V", get_dvc_sensor_state, NULL);

ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_AFE_TEMP, afe_temp, "°C", get_dvc_sensor_state, NULL);
ADD_MQTT_ENTITY_SENSOR(DVC_SENSOR_TYPE_BAT_TEMP, bat_temp, "°C", get_dvc_sensor_state, NULL);

typedef enum
{
    DVC_SWITCH_TYPE_CHG, /* 充电开关 */
    DVC_SWITCH_TYPE_DSG, /* 放电开关 */
    DVC_SWITCH_TYPE_AES, /* 均衡开关 */
    DVC_SWITCH_TYPE_MAX,
} dvc_switch_type_t;
static uint8_t get_dvc_switch_state(void *user_data, uint8_t id, char *buf, uint8_t len)
{
    if (!gloab_dvc || id >= DVC_SWITCH_TYPE_MAX)
        return 0;
    dvc_t dvc = gloab_dvc;
    if (id == DVC_SWITCH_TYPE_CHG)
        return snprintf(buf, len, "%s", dvc->cfg.cfg0.chg_en ? "ON" : "OFF");
    else if (id == DVC_SWITCH_TYPE_DSG)
        return snprintf(buf, len, "%s", dvc->cfg.cfg0.dsg_en ? "ON" : "OFF");
    else if (id == DVC_SWITCH_TYPE_AES)
        return snprintf(buf, len, "%s", dvc->aes ? "ON" : "OFF");
    return 0;
}
static void set_dvc_switch_state(void *user_data, uint8_t id, const char *state)
{
    if (!gloab_dvc || id >= DVC_SWITCH_TYPE_MAX)
        return;
    dvc_t dvc = gloab_dvc;

    if (id == DVC_SWITCH_TYPE_CHG)
    {
        dvc_chg(dvc, strstr(state, "ON") > 0, DVC_EVENT_FLAG_USER);
        dvc_config_commit(dvc);
    }
    else if (id == DVC_SWITCH_TYPE_DSG)
    {
        dvc_dsg(dvc, strstr(state, "ON") > 0, DVC_EVENT_FLAG_USER);
        dvc_config_commit(dvc);
    }
    else if (id == DVC_SWITCH_TYPE_AES)
        dvc_aes(dvc, strstr(state, "ON") > 0, DVC_EVENT_FLAG_USER);
}

ADD_MQTT_ENTITY_SWITCH(DVC_SWITCH_TYPE_CHG, afe_chg, get_dvc_switch_state, set_dvc_switch_state, NULL);
ADD_MQTT_ENTITY_SWITCH(DVC_SWITCH_TYPE_DSG, afe_dsg, get_dvc_switch_state, set_dvc_switch_state, NULL);
ADD_MQTT_ENTITY_SWITCH(DVC_SWITCH_TYPE_AES, afe_aes, get_dvc_switch_state, set_dvc_switch_state, NULL);